using System;
using CommonBehaviors.Actions;
using FarmerJoe.Helpers;
using FarmerJoe.Helpers.Logging;
using FarmerJoe.Helpers.Units;
using FarmerJoe.Settings;
using Styx;
using Styx.CommonBot;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;

namespace FarmerJoe.Classes
{
    public static partial class Warlock
    {
        #region Combat

        private static bool NeedSoulShard
        {
            get
            {
                if ((Me.GetCurrentPower(WoWPowerType.SoulShards) < Me.MaxSoulShards || TalentsAndGlyphs.HasGlyph("Soul Consumption")) && !CT.Elite && CT.HealthPercent < FpswareSettings.Instance.Warlock.AfflictionDrainSoulFinisherHealth) return true;
                if (((Me.GetCurrentPower(WoWPowerType.SoulShards) < Me.MaxSoulShards || TalentsAndGlyphs.HasGlyph("Soul Consumption"))) && CT.Elite && CT.HealthPercent < FpswareSettings.Instance.Warlock.AfflictionDrainSoulFinisherHealth*0.5) return true;

                if (!FpswareSettings.Instance.Warlock.AfflictionDrainSoulCombatMinShards.Contains("never") &&
                    Me.GetCurrentPower(WoWPowerType.SoulShards) <= Convert.ToInt32(FpswareSettings.Instance.Warlock.AfflictionDrainSoulCombatMinShards)) return true;

                return false;
            }
        }

        private static WoWUnit _currentTarget;
        public static Composite CombatBehavior_Afflication
        {
            get
            {
                return new PrioritySelector(

                    Spells.WaitForCast(),
                    Misc.EnsureTarget(),

                    SummonPet(),
                    PetSpells(),

                    AllFormsHeal(),
                    Common.UseHealthManaRegenAgent(ClassParser.HealthPotion, ClassParser.ManaPotion),

                    Inventory.UseTrinket1(),
                    Inventory.UseTrinket2(),

                    Movement.MoveToLOS(),
                    Movement.FaceTarget(),
                    Movement.ForceFacingTarget(),
                    Pets.DefendMe(),
                    Movement.Fixes(),


                    // Somehow we've got a target that is not hostile or attackable. Blacklist it and move on
                    new Decorator(ret => Me.GotTarget & (!CT.Attackable || CT.IsFriendly),
                        new Sequence(
                            new Action(context => Log.Write(Colours.InformativeColour, "Somehow we've got a target that is friendly or not attackable, blacklisting it and moving on.")),
                            new Action(context => Blacklist.Add(CT, TimeSpan.FromMinutes(1))),
                            new Action(context => Me.ClearTarget())
                        )),


                    // Combat rotation goes here

                    // Soul Swap to apply all DoTs
                    // If we already have 1 (and only ONE) DoT then do it anyway
                    new Decorator(ret => (Me.CurrentSoulShards > 1 || Me.ActiveAuras.ContainsKey("Soulburn")) && CountOfMyCurses <= 1 && SpellManager.HasSpell(86121) && WoWSpell.FromId(86121).CanCast && CT.HealthPercent > 40 && !FpswareSettings.Instance.Warlock.AfflictionSoulSwap.Contains("never") && Timers.AutoExpire("Soulburn Soul Swap", 4000) && !AddsAndOthers.HasAdds,
                        new Sequence(
                            new DecoratorContinue(ret => !Me.ActiveAuras.ContainsKey("Soulburn"),
                                new Sequence(
                                    Spells.Buff("Soulburn", ret => Me, ret => !Me.HasAura("Soulburn"), false),
                                    new WaitContinue(2, ret => Me.HasAura("Soulburn"), new ActionAlwaysSucceed())
                                    )),

                            new DecoratorContinue(ret => CT.Distance >= 40,
                                    new Action(context => Movement.MoveToTarget(true, 35f))
                                    ),

                            new Decorator(ret => Me.ActiveAuras.ContainsKey("Soulburn") && CT.Distance <= 40 && CountOfMyCurses <= 1,
                                new Sequence(
                                    //Spells.Buff("Soul Swap",ret=> Me.HasAura("Soulburn"))
                                    //new Action(context => Spells.LUACast("Soul Swap"))
                                    //new Action(context => SpellManager.Cast("Soul Swap"))
                                    new Action(context => Log.Write("Casting Soul Swap (with Soulburn)")),
                                    new Action(context => SpellManager.Cast("Soul Swap"))
                                    ))
                        )),


                    // Seed of Corruption
                    new Decorator(ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionSeedOfCorruptionWhen) && !FpswareSettings.Instance.Warlock.AfflictionSeedOfCorruption.Contains("never") && !CT.HasMyAura("Seed of Corruption") && SpellManager.HasSpell("Seed of Corruption") && Timers.SpellOkToCast("Seed of Corruption", 5000) && CT.Distance < 40 && IsCastingOK,
                        new Sequence(
                            new DecoratorContinue(ret => !Me.HasAura("Soulburn") && Me.CurrentSoulShards >= 1 && !FpswareSettings.Instance.Warlock.AfflictionSeedOfCorruptionSoulburn.Contains("never"),
                                new Sequence(
                                    Spells.Buff("Soulburn", ret => Me, ret => !Me.HasAura("Soulburn"), false),
                                    new WaitContinue(2, ret => Me.HasAura("Soulburn"), new ActionAlwaysSucceed())
                                    )),

                            new Decorator(ret => CT.Distance <= 40,
                                new Sequence(
                                    Spells.Cast("Seed of Corruption")))
                        )),


                    Spells.Cast("Mortal Coil", ret => Me.HealthPercent <= FpswareSettings.Instance.Warlock.AfflictionMortalCoilHealth),

                    // Stop Drain Soul if we have max shards AND the target's HP > 25% AND we don't have Glyph of Soul Consumption
                    new Decorator(ret => Me.IsCasting && Me.CastingSpell.Name == "Drain Soul" && Me.GetCurrentPower(WoWPowerType.SoulShards) >= Me.MaxSoulShards && CT.HealthPercent > FpswareSettings.Instance.Warlock.AfflictionDrainSoulFinisherHealth * 1.125,
                        new Sequence(
                            new Action(delegate { SpellManager.StopCasting(); }),
                            new ActionAlwaysFail()
                        )),

                    // Stop Casting Malefic Grasp and start casting Drain Soul if target < 25 HP
                    new Decorator(ret => Me.IsCasting && (Me.CastingSpell.Name == "Malefic Grasp" || Me.CastingSpell.Name == "Shadow Bolt") && NeedSoulShard,
                        new Sequence(
                            new Action(delegate { Log.Write(Colours.InformativeColour,"Canceling Malefic Grasp in order to cast Drain Soul"); }),
                            new Action(delegate { SpellManager.StopCasting(); }),
                            new ActionAlwaysSucceed()
                        )),

                    // Drain Soul
                    // If target HP% < finisher health (or if elite, reduce finisher health by half). If we're below min soul shard count.
                    new Decorator(ret=> NeedSoulShard,
                        new Sequence(
                            new DecoratorContinue(ret => Me.IsCasting && Me.CastingSpell.Name != "Drain Soul",
                                new Sequence(
                                    new Action(context => SpellManager.StopCasting()),
                                    new WaitContinue(1, ret => !SpellManager.GlobalCooldown, new ActionAlwaysSucceed())
                                    )),

                            new Decorator(ret => CT.Distance <= 40,
                                new Sequence(
                                    Spells.Cast("Drain Soul"),
                                    new WaitContinue(1, ret => false, new ActionAlwaysSucceed())
                                    ))
                            )),

                    // Protect ourself from spells if we can
                    new Decorator(ret => !FpswareSettings.Instance.Warlock.AfflictionTwilightWard.Contains("never") && Me.GotTarget && CT.IsCasting && CT.CastingSpell.CastTime > 1000 && CT.CurrentTarget.Guid == Me.Guid,
                            new PrioritySelector(
                                Spells.Cast("Twilight Ward", ret => CT.CastingSpell.School == WoWSpellSchool.Shadow || CT.CastingSpell.School == WoWSpellSchool.Holy)
                                )),

                    // Fear me bitch!
                    /*
                    new Decorator(ret => AddsAndOthers.HasAdds && FearedMob == null && MobToFear != null,
                        new Sequence(
                            new WaitContinue(5, ret => !SpellManager.GlobalCooldown && !Me.IsCasting && !Me.IsChanneling, new ActionAlwaysSucceed()),
                            new Action(context => Log.Write(Colours.InformativeColour, "Fearing add!")),
                            Spells.Buff("Fear", ret => MobToFear, ret => SpellManager.CanCast("Fear"), false)
                            )),
                     */

                    Spells.Cast("Grimoire: " + FpswareSettings.Instance.Warlock.AfflictionGrimoirePet, ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionGrimoireOfService)),
                    //Spells.Cast("Grimoire of Service", ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionGrimoireOfService) && SpellManager.HasSpell("Grimoire of Service")),
                    Spells.Cast("Dark Soul", ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionDarkSoul) && !WoWSpell.FromId(113860).Cooldown && !Me.HasAura("Dark Soul: Misery")),
                    Spells.Cast("Grimoire of Sacrifice", ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionGrimoireOfSacrifice) && Me.GotAlivePet && !Me.HasAura("Grimoire of Sacrifice")),

                    // Curse of the Elements
                      new Decorator(ret => IsCastingOK && CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionCurseOfTheElements) && CT.AuraTimeLeft("Curse of the Elements")<3 && SpellManager.HasSpell("Curse of the Elements"),
                        new Sequence(
                            new DecoratorContinue(ret => !Me.HasAura("Soulburn") && CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionCurseOfTheElementsSoulburnAdds),
                                new Sequence(
                                    Spells.Buff("Soulburn", ret => Me, ret => !Me.HasAura("Soulburn"), false),
                                    new WaitContinue(2, ret => Me.HasAura("Soulburn") && !SpellManager.GlobalCooldown, new ActionAlwaysSucceed())
                                    )),

                            new Decorator(ret => CT.Distance <= 40,
                                new Sequence(
                                    Spells.Cast("Curse of the Elements")
                                    ))
                        )),


                    // Soulburn, Soul Swap adds. Apply all 3 DoTs at once. 
                    new Decorator(ret => !FpswareSettings.Instance.Warlock.AfflictionSoulSwap.Contains("never") && SpellManager.HasSpell(86121) && CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionSoulSwapSoulburn) && (Me.CurrentSoulShards >= 1 || Me.HasAura("Soulburn")) && AddsAndOthers.HasAdds && DoTAddTargetSoulBurnSoulSwap != null,
                        new Sequence(
                            new DecoratorContinue(ret => !Me.HasAura("Soulburn"),
                                new Sequence(
                                    Spells.Buff("Soulburn", ret => Me, ret => !Me.ActiveAuras.ContainsKey("Soulburn"), false),
                                    new Action(context => Log.Write(Colours.InformativeColour, "Using Soulburn for Soul Sawp on " + Extensions.SafeName(DoTAddTargetSoulBurnSoulSwap))),
                                    new WaitContinue(2, ret => Me.ActiveAuras.ContainsKey("Soulburn") && !SpellManager.GlobalCooldown, new ActionAlwaysSucceed())
                                    )),

                            new DecoratorContinue(ret => Me.ActiveAuras.ContainsKey("Soulburn"),
                                new Sequence(
                                    //new Action(context => Log.Write(Colours.InformativeColour, "Using Soulburn for Soul Sawp on " + Extensions.SafeName(DoTAddTargetSoulBurnSoulSwap))),
                                    //Spells.Cast("Soul Swap",ret=> DoTAddTargetSoulBurnSoulSwap)
                                    //new Action(context => _currentTarget = CT),
                                    //new Action(context => DoTAddTargetSoulBurnSoulSwap.Target()),
                                    //new WaitContinue(1, ret => false, new ActionAlwaysSucceed()),
                                    //new WaitContinue(2, ret => Me.CurrentTargetGuid != _currentTarget.Guid, new ActionAlwaysSucceed()),
                                    //new Action(context => Spells.LUACast("Soul Swap"))
                                    new Action(context => Log.Write("Casting Soul Swap (with Soulburn) on add " + DoTAddTargetSoulBurnSoulSwap.Name)),
                                    new Action(context => SpellManager.Cast("Soul Swap", DoTAddTargetSoulBurnSoulSwap))
                                    //new WaitContinue(1, ret => false, new ActionAlwaysSucceed()),
                                    //new Action(context => _currentTarget.Target()),
                                    //new WaitContinue(2, ret => Me.CurrentTargetGuid == _currentTarget.Guid, new ActionAlwaysSucceed())
                                    
                                    ))
                    )),


                    // Life Tap
                    new Decorator(ret => !FpswareSettings.Instance.Warlock.AfflictionLifeTap.Contains("never") && Me.HealthPercent > FpswareSettings.Instance.Warlock.AfflictionLifeTapMinHealth && Me.ManaPercent < FpswareSettings.Instance.Warlock.AfflictionLifeTapMana && IsCastingOK,
                        new Sequence(
                            Spells.Cast("Life Tap"),
                            new WaitContinue(2, ret => !SpellManager.GlobalCooldown, new ActionAlwaysSucceed())
                            )),

                    Spells.Cast("Health Funnel", ret => !Spells.HasSpell(108415) && Me.GotAlivePet && Me.Pet.HealthPercent < FpswareSettings.Instance.Warlock.AfflictionHealPetHealth && Me.Pet.Distance < 45 && SpellManager.HasSpell("Health Funnel") && !SpellManager.Spells["Health Funnel"].Cooldown),
                    


                    // Trying to fix the not facing target issue
                    new Decorator(ret => !Me.IsMoving && !Me.Mounted && FpswareSettings.Instance.Warlock.CCControlledMovement.Contains("always") && Me.GotTarget && !Me.IsSafelyFacing(CT.Location),
                        new Sequence(
                            new Action(context => CT.Face()),
                            new ActionAlwaysFail()
                        )),

                        // This is our basic debuff logic.
                        // (RE)DOT dependant on target being ELITE or not
                        new Decorator(ret => !CT.Elite,
                            new PrioritySelector(
                                Spells.Cast("Corruption", ret => CT.AuraTimeLeft("Corruption") < 3 && CT.HealthPercent > 15 && CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionCorruption)),
                                Spells.Cast("Agony", ret => CT.AuraTimeLeft("Agony") < 3 && CT.HealthPercent > 15 && CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionAgony)),
                                new Decorator(ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionUnstableAffliction) && SpellManager.HasSpell("Unstable Affliction") && CT.AuraTimeLeft("Unstable Affliction") < 3 && Timers.SpellOkToCast("Unstable Affliction", 2700) && CT.HealthPercent > FpswareSettings.Instance.Warlock.AfflictionUnstableAfflictionMinHealth,
                                    new Sequence(
                                        new WaitContinue(2, ret => !SpellManager.GlobalCooldown && !Me.IsCasting, new ActionAlwaysSucceed()),
                                        Spells.Cast("Unstable Affliction")
                                    )),

                                new Decorator(ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionHaunt) && SpellManager.HasSpell("Haunt") && CT.AuraTimeLeft("Haunt") < 3 && Timers.SpellOkToCast("Haunt", 3000) && CT.HealthPercent > FpswareSettings.Instance.Warlock.AfflictionHauntMinHealth,
                                    new Sequence(
                                        new WaitContinue(2, ret => !SpellManager.GlobalCooldown && !Me.IsCasting, new ActionAlwaysSucceed()),
                                        Spells.Cast("Haunt", ret=> CT.HealthPercent > FpswareSettings.Instance.Warlock.AfflictionHauntMinHealth)
                                    ))
                                )),
                        new Decorator(ret=> CT.Elite,
                            new PrioritySelector(
                                Spells.Cast("Corruption", ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionCorruption) && CT.AuraTimeLeft("Corruption") < 3),
                                Spells.Cast("Agony", ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionAgony) && CT.AuraTimeLeft("Agony") < 3),
                                new Decorator(ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionUnstableAffliction) && SpellManager.HasSpell("Unstable Affliction") && !CT.HasMyAura("Unstable Affliction") && Timers.SpellOkToCast("Unstable Affliction", 2500),
                                    new Sequence(
                                        new WaitContinue(2, ret=> !SpellManager.GlobalCooldown && !Me.IsCasting, new ActionAlwaysSucceed()),
                                        Spells.Cast("Unstable Affliction", ret => CT.AuraTimeLeft("Unstable Affliction") < 3 && CT.HealthPercent > 2)
                                    )),

                                new Decorator(ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionHaunt) && SpellManager.HasSpell("Haunt") && CT.AuraTimeLeft("Haunt") < 3 && Timers.SpellOkToCast("Haunt", 3000),
                                    new Sequence(
                                        new WaitContinue(2, ret=> !SpellManager.GlobalCooldown && !Me.IsCasting, new ActionAlwaysSucceed()),
                                        Spells.Cast("Haunt", ret => CT.AuraTimeLeft("Haunt") < 3 && CT.HealthPercent > 2)
                                    ))
                                )),


                                // Drain Life. But first check if we need to face the target
                                  new Decorator(ret => Me.HealthPercent <= FpswareSettings.Instance.Warlock.AfflictionDrainLifeHealth && Me.GotTarget,
                                       new Sequence(
                                         new DecoratorContinue(ret => !Me.IsSafelyFacing(CT, 45),
                                            new Sequence(
                                                new Action(context => CT.Face()),
                                                new WaitContinue(2, ret => false, new ActionAlwaysSucceed())
                                                )),

                                        Spells.Cast("Drain Life", ret => Me.HealthPercent <= FpswareSettings.Instance.Warlock.AfflictionDrainLifeHealth)
                                    )),

                     // Drain Life
                     /*
                                  new Decorator(ret => Me.GotTarget && Me.Combat && Me.HealthPercent <= FpswareSettings.Instance.Warlock.AfflictionDrainLifeHealth && FpswareSettings.Instance.Warlock.AfflictionDrainLifePriority.Contains("medium"),// && Me.CastingSpell.Name != "Drain Life",
                                    new Sequence(
                                        
                                        //new DecoratorContinue(ret => Me.IsCasting && Me.CastingSpell.Name != "Drain Life" && Me.CastingSpell.Name != "Drain Soul",
                                        new DecoratorContinue(ret => Me.IsCasting && (Me.CastingSpell.Name == "Malefic Grasp" || Me.CastingSpell.Name == "Shadow Bolt"),
                                            new Sequence(
                                                new Action(context => Log.Write(Colours.InformativeColour, "Stop casting before casting Drain Life")),
                                                new Action(context => SpellManager.StopCasting()),
                                                new Wait(2, ret => !SpellManager.GlobalCooldown, new ActionAlwaysSucceed())
                                                )),

                                        new DecoratorContinue(ret => !Me.IsCasting && Timers.AutoExpire("Soulburn Drain Life",2000) && !Me.ActiveAuras.ContainsKey("Soulburn") && FpswareSettings.Instance.Warlock.AfflictionDrainLifeSoulburn.Contains("always") && Me.GetCurrentPower(WoWPowerType.SoulShards) >= Convert.ToInt32(FpswareSettings.Instance.Warlock.AfflictionDrainLifeSoulburnMinShards), //&& (!Me.IsCasting || Me.CastingSpell.Name != "Drain Life"),
                                            new Sequence(
                                                Spells.Buff("Soulburn", ret => Me, ret => !Me.HasAura("Soulburn"), false),
                                                new Action(context => Log.Write(Colours.InformativeColour, "Soulburn before casting Drain Life")),
                                                new Wait(1, ret => false, new ActionAlwaysSucceed())
                                                )),

                                        new DecoratorContinue(//ret => CT.Distance <= 40,
                                            new Sequence(
                                                //new Action(context => Log.Write(Colours.InformativeColour, "Just about to wait for GCD")),
                                                //new WaitContinue(2, ret => !SpellManager.GlobalCooldown && !Me.IsCasting && !Me.IsMoving, new ActionAlwaysSucceed()),
                                                
                                                Spells.Cast("Drain Life"),
                                                new Action(context => Log.Write(Colours.InformativeColour, "Drain Life bitch!"))
                                                ))
                      
                                )),
                      */



                    // ======================= [Multi-DoT Adds] =======================
                    new Decorator(ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionCorruptionAdds) && AddsAndOthers.HasAdds && DoTAddTarget("Corruption") != null,
                        new Sequence(
                            Spells.Buff("Corruption", ret => DoTAddTarget("Corruption"), ret => IsCastingOK, true),
                            new Action(context => Log.Write(Colours.InformativeColour, "Dotting add with Corruption")),
                            new WaitContinue(2, ret => !SpellManager.GlobalCooldown, new ActionAlwaysSucceed())
                                )),

                    new Decorator(ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionAgonyAdds) && AddsAndOthers.HasAdds && DoTAddTarget("Agony") != null,
                        new Sequence(
                            Spells.Buff("Agony", ret => DoTAddTarget("Agony"), ret => IsCastingOK, true),
                            new Action(context => Log.Write(Colours.InformativeColour, "Dotting add with Agony")),
                            new WaitContinue(2, ret => !SpellManager.GlobalCooldown, new ActionAlwaysSucceed())
                                )),

                    new Decorator(ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionUnstableAfflictionAdds) && AddsAndOthers.HasAdds && DoTAddTarget("Unstable Affliction") != null,
                        new Sequence(
                            Spells.Buff("Unstable Affliction", ret => DoTAddTarget("Unstable Affliction"), ret => IsCastingOK && DoTAddTarget("Unstable Affliction").HealthPercent > FpswareSettings.Instance.Warlock.AfflictionUnstableAfflictionMinHealth, true),
                            new Action(context => Log.Write(Colours.InformativeColour, "Dotting add with Unstable Affliction")),
                            new WaitContinue(2, ret => !SpellManager.GlobalCooldown, new ActionAlwaysSucceed())
                                )),
                    // ======================= [Multi-DoT Adds] =======================
                    



                    // [SpellManager] Malefic Grasp (103103) overrides Shadow Bolt (686)
                    Spells.Cast("Shadow Bolt", ret=> IsCastingOK && CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionMaleficGrasp)),

                    // Fall through spell
                    Spells.Cast("Fel Flame", ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.AfflictionFelFlame) && IsCastingOK),


                    new Decorator(ret => Me.IsCasting || Me.IsChanneling, new Action(context => RunStatus.Success)),
                    Movement.MoveToTarget(true, 36f)
                    );
            }
        }
        #endregion

        #region Pull
        public static Composite PullBehavior_Afflication
        {
            get
            {
                return new PrioritySelector(

                    Spells.WaitForCast(),
                    Misc.EnsureTarget(),
                    new Decorator(ret => Me.Mounted, new Action(context => Mount.Dismount())),
                    Movement.FaceTarget(),
                    Movement.ForceFacingTarget(),
                    Movement.MoveToLOS(),
                    Movement.Fixes(),

                    // Somehow we've got a target that is not hostile or attackable. Blacklist it and move on
                    new Decorator(ret => !CT.Attackable || CT.IsFriendly,
                        new Sequence(
                            new Action(context => Log.Write(Colours.InformativeColour, "Somehow we've got a target that is friendly or not attackable, blacklisting it and moving on.")),
                            new Action(context => Blacklist.Add(CT, TimeSpan.FromMinutes(1))),
                            new Action(context => Me.ClearTarget())
                        )),

                    new Decorator(ret => Me.GotAlivePet && Timers.SpellOkToCast("Pet Attack Pull", 2000) && ((Me.Pet.GotTarget && Me.Pet.CurrentTargetGuid != Me.CurrentTargetGuid) || !Me.Pet.GotTarget),
                        new Sequence(
                            new Action(delegate { Pets.CastPetAction("Attack"); }),
                            new Action(delegate { Timers.Reset("Pet Attack Pull"); }),
                            new Action(ctx => RunStatus.Failure)
                            )),

                    // User defined pull options
                    new Decorator(ret => FpswareSettings.Instance.Warlock.AfflictionPull.Contains("user defined"),
                                  new PrioritySelector(

                                      new Decorator(ret => FpswareSettings.Instance.Warlock.AfflictionPullSoulburnSoulSwap.Contains("always") && SpellManager.HasSpell(86121) && Me.CurrentSoulShards >= 1 && !Me.IsMoving && Timers.AutoExpire("Soulburn Soul Swap", 5000),
                                           new Sequence(
                                                new DecoratorContinue(ret => !Me.HasAura("Soulburn"),
                                                    new Sequence(
                                                        Spells.Buff("Soulburn", ret => Me, ret => !Me.HasAura("Soulburn"), false),
                                                        new Wait(2, ret => Me.HasAura("Soulburn"), new ActionAlwaysSucceed())
                                                        )),

                                                new DecoratorContinue(ret => CT.Distance >= 40,
                                                        new Action(context => Movement.MoveToTarget(true, 35f))
                                                        ),

                                                new Decorator(ret => Me.HasAura("Soulburn") && CT.Distance <= 40,
                                                    new Sequence(
                                                        //new Action(context => Spells.LUACast("Soul Swap")),
                                                        //Spells.Cast("Soul Swap")
                                                        //Spells.Buff("Soul Swap",ret=> Me.HasAura("Soulburn"))
                                                        new Action(context => Log.Write("Casting Soul Swap (with Soulburn)")),
                                                        new Action(context => SpellManager.Cast("Soul Swap"))
                                                        ))
                                                )
                                          
                                      ),

                                      new Decorator(ret=> !Me.ActiveAuras.ContainsKey("Soulburn"),
                                          new PrioritySelector(
                                              Spells.Cast("Unstable Affliction", ret => FpswareSettings.Instance.Warlock.AfflictionPullUnstableAffliction.Contains("always") && !Me.IsMoving && Timers.SpellOkToCast("Unstable Affliction", 3000)),
                                              Spells.Cast("Haunt", ret => FpswareSettings.Instance.Warlock.AfflictionPullHaunt.Contains("always") && !Me.IsMoving && Timers.SpellOkToCast("Haunt", 2700)),
                                              Spells.Cast("Corruption", ret => !Me.IsMoving && FpswareSettings.Instance.Warlock.AfflictionPullCorruption.Contains("always")),
                                              Spells.Cast("Shadow Bolt", ret => !Me.IsMoving && FpswareSettings.Instance.Warlock.AfflictionPullMaleficGrasp.Contains("always") && !Me.IsMoving)    
                                          ))
                                      

                                      )),


                    // Automatic fall through stuff
                    new Decorator(ret => FpswareSettings.Instance.Warlock.AfflictionPull.Contains("automatic"),
                                  new PrioritySelector(

                                      Spells.Cast("Unstable Affliction", ret => !Me.IsMoving && Timers.SpellOkToCast("Unstable Affliction", 2700)),
                                      Spells.Cast("Haunt", ret => !Me.IsMoving && Timers.SpellOkToCast("Haunt", 2700)),
                                      Spells.Cast("Shadow Bolt", ret => !Me.IsMoving)

                                      )),

                    new Decorator(ret => Me.IsCasting || Me.IsChanneling, new Action(context => RunStatus.Success)),

                    
                    Movement.PullApproach(),
                    Movement.MoveToTarget(true, 35f)
                    );
            }
        }
        #endregion

    }
}